// baltzo_defaultzoneinfocache.t.cpp                                  -*-C++-*-
#include <baltzo_defaultzoneinfocache.h>

#include <baltzo_datafileloader.h>
#include <baltzo_localtimedescriptor.h>
#include <baltzo_testloader.h>
#include <baltzo_zoneinfo.h>

#include <bdls_filesystemutil.h>
#include <bdls_pathutil.h>

#include <bdlt_date.h>
#include <bdlt_datetime.h>

#include <bdlt_currenttime.h>

#include <bslma_allocator.h>
#include <bslma_default.h>
#include <bslma_defaultallocatorguard.h>
#include <bslma_testallocator.h>
#include <bslmt_threadutil.h>

#include <bsls_assert.h>
#include <bsls_asserttest.h>
#include <bsls_types.h>

#include <bsl_cstdlib.h>
#include <bsl_fstream.h>
#include <bsl_iostream.h>
#include <bsl_map.h>

#include <bsl_c_stdlib.h>   // 'putenv'

using namespace BloombergLP;
using namespace std;

//=============================================================================
//                              TEST PLAN
//-----------------------------------------------------------------------------
//                              Overview
//                              --------
// 'baltzo::DefaultZoneinfoCache' is a mechanism that implements the unique,
// process-wide, singleton time zone cache object.
//
// Global Concerns:
//: o Precondition violations are detected in appropriate build modes.
//
// Global Assumptions:
//: o All explicit memory allocations are presumed to use the global or default
//:   allocator.
//-----------------------------------------------------------------------------
// CLASS METHODS
// [ 3] const char *defaultZoneinfoDataLocation();
// [ 5] baltzo::ZoneinfoCache *defaultCache(baltzo::ZoneinfoCache *cache);
// [ 2] void loadDefaultZoneinfoDataLocations(bsl::vector<char *> *locations);
// [ 4] baltzo::ZoneinfoCache *setDefaultCache(baltzo::ZoneinfoCache *cache);
//
////---------------------------------------------------------------------------
// [ 1] BREATHING TEST: 'baltzo::DefaultZoneinfoCache'
// [ 6] USAGE EXAMPLE
//-----------------------------------------------------------------------------
//=============================================================================

// ============================================================================
//                      STANDARD BDE ASSERT TEST MACRO
// ----------------------------------------------------------------------------
static int testStatus = 0;
static void aSsErT(int c, const char *s, int i)
{
    if (c) {
        cout << "Error " << __FILE__ << "(" << i << "): " << s
             << "    (failed)" << endl;
        if (testStatus >= 0 && testStatus <= 100) ++testStatus;
    }
}
#define ASSERT(X) { aSsErT(!(X), #X, __LINE__); }

// ============================================================================
//                   STANDARD BDE LOOP-ASSERT TEST MACROS
// ----------------------------------------------------------------------------

#define LOOP_ASSERT(I,X) {                                                    \
    if (!(X)) { cout << #I << ": " << I << "\n"; aSsErT(1, #X, __LINE__);}}

#define LOOP2_ASSERT(I,J,X) {                                                 \
    if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": "                 \
              << J << "\n"; aSsErT(1, #X, __LINE__); } }

#define LOOP3_ASSERT(I,J,K,X) {                                               \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t"     \
              << #K << ": " << K << "\n"; aSsErT(1, #X, __LINE__); } }

#define LOOP4_ASSERT(I,J,K,L,X) {                                             \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" <<  \
       #K << ": " << K << "\t" << #L << ": " << L << "\n";                    \
       aSsErT(1, #X, __LINE__); } }

#define LOOP5_ASSERT(I,J,K,L,M,X) {                                           \
   if (!(X)) { cout << #I << ": " << I << "\t" << #J << ": " << J << "\t" <<  \
       #K << ": " << K << "\t" << #L << ": " << L << "\t" <<                  \
       #M << ": " << M << "\n";                                               \
       aSsErT(1, #X, __LINE__); } }

// ============================================================================
//                     SEMI-STANDARD TEST OUTPUT MACROS
// ----------------------------------------------------------------------------
#define P(X)  cout << #X " = " << (X) << endl; // Print identifier and value.
#define Q(X)  cout << "<| " #X " |>" << endl;  // Quote identifier literally.
#define P_(X) cout << #X " = " << (X) << ", "<< flush; // P(X) without '\n'
#define T_    cout << "\t" << flush;          // Print a tab (w/o newline)
#define L_ __LINE__                           // current Line number

// ============================================================================
//                     NEGATIVE-TEST MACRO ABBREVIATIONS
// ----------------------------------------------------------------------------

#define ASSERT_SAFE_PASS(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_PASS(EXPR)
#define ASSERT_SAFE_FAIL(EXPR) BSLS_ASSERTTEST_ASSERT_SAFE_FAIL(EXPR)
#define ASSERT_PASS(EXPR)      BSLS_ASSERTTEST_ASSERT_PASS(EXPR)
#define ASSERT_FAIL(EXPR)      BSLS_ASSERTTEST_ASSERT_FAIL(EXPR)
#define ASSERT_OPT_PASS(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_PASS(EXPR)
#define ASSERT_OPT_FAIL(EXPR)  BSLS_ASSERTTEST_ASSERT_OPT_FAIL(EXPR)

// ============================================================================
//                   GLOBAL TYPEDEFS/CONSTANTS FOR TESTING
// ----------------------------------------------------------------------------
typedef baltzo::DefaultZoneinfoCache Obj;
typedef baltzo::ZoneinfoCache        Cache;
typedef baltzo::Zoneinfo             Zone;
typedef bsl::string                 Id;

//=============================================================================
//                                USAGE EXAMPLE
//-----------------------------------------------------------------------------
///Usage
///-----
// The following usage example demonstrates configuring and accessing the
// default Zoneinfo cache object.
//
///Example 1: Accessing the Default Zoneinfo Cache Object
/// - - - - - - - - - - - - - - - - - - - - - - - - - - -
// A common application of the 'baltzo::DefaultZoneinfoCache' is to determine
// the appropriate time-zone information to use for an operation that accepts a
// Zoneinfo cache as an optional argument (e.g., 'baltzo_timezoneutil').  Note
// that this pattern is also seen for the default allocator (see
// 'bslma_default').
//
// First, we declare a function 'getLocalTimeDescriptor' that returns the
// local-time descriptor for given time in a particular time zone.  This method
// takes an optional 'baltzo::ZoneinfoCache' argument, 'zoneinfoCache', where,
// if 'zoneinfoCache' is unspecified, the default Zoneinfo cache is used for
// the operation:
//..
    int getLocalTimeDescriptor(baltzo::LocalTimeDescriptor *result,
                               const bdlt::Datetime&        utcTime,
                               const char                  *timeZoneId,
                               baltzo::ZoneinfoCache       *zoneinfoCache = 0)
        // Load into the specified 'result' the local time descriptor for the
        // that the UTC time specified by the specified 'utcTime' for the time
        // zone identified by the specified 'timeZoneId'.  Return 0 on success,
        // and a non-zero value otherwise.  Optionally specify a
        // 'zoneinfoCache' used to retrieve time-zone information.  If
        // 'zoneinfoCache' is 0, the currently installed default Zoneinfo cache
        // is used.
    {
//..
// We call the 'baltzo::DefaultZoneinfoCache::defaultCache' method, which
// returns 'zoneinfoCache' if 'zoneinfoCache' is not 0, and the currently
// installed Zoneinfo cache otherwise.
//..
        baltzo::ZoneinfoCache *cache =
                     baltzo::DefaultZoneinfoCache::defaultCache(zoneinfoCache);
        ASSERT(0 != cache);
//..
// Next, now that we have a of Zoneinfo cache object, we access the time-zone
// data for the 'timeZoneId', and obtain the current local-time descriptor:
//..
        const baltzo::Zoneinfo *zoneinfo = cache->getZoneinfo(timeZoneId);
        if (0 == zoneinfo) {

            // Data for 'timeZoneId' is not available in the cache, so return
            // an error.

            return 1;                                                 // RETURN
        }

        baltzo::Zoneinfo::TransitionConstIterator it =
                                   zoneinfo->findTransitionForUtcTime(utcTime);

        if (it == zoneinfo->endTransitions()) {

            // No information available for the current time.

            return 1;                                                 // RETURN
        }

        *result = it->descriptor();
        return 0;
    }
//..

// ============================================================================
//                   GLOBAL TYPEDEFS/CONSTANTS FOR TESTING
// ----------------------------------------------------------------------------

// DATA from GMT
static const unsigned char GMT_DATA[] = {
    0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x47, 0x4d, 0x54, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66,
    0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4d,
    0x54, 0x00, 0x00, 0x00, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0a,
};

// DATA from Etc/UTC
const char unsigned ETC_UTC_DATA[] = {
      0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
    , 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    , 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00
    , 0x00, 0x00, 0x55, 0x54, 0x43, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66
    , 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01
    , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
    , 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x54
    , 0x43, 0x00, 0x00, 0x00, 0x0a, 0x55, 0x54, 0x43, 0x30, 0x0a  };

static const char unsigned AMERICA_NEW_YORK_DATA[] = {
      0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
    , 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb
    , 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x9e, 0xa6, 0x1e, 0x70
    , 0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70, 0xa1, 0x9a, 0xcd, 0x60
    , 0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0, 0xa4, 0x6a, 0xae, 0x70
    , 0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0, 0xa7, 0x15, 0x89, 0x60
    , 0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0, 0xaa, 0x13, 0x8e, 0xf0
    , 0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0, 0xac, 0xbe, 0x69, 0xe0
    , 0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0, 0xaf, 0xb3, 0x34, 0xf0
    , 0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70, 0xb2, 0x67, 0x4a, 0x60
    , 0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60, 0xb5, 0x5c, 0x15, 0x70
    , 0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70, 0xb8, 0x06, 0xf0, 0x60
    , 0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60, 0xbb, 0x04, 0xf5, 0xf0
    , 0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0, 0xbd, 0xaf, 0xd0, 0xe0
    , 0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0, 0xc0, 0xa4, 0x9b, 0xf0
    , 0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0, 0xc3, 0x4f, 0x76, 0xe0
    , 0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0, 0xc6, 0x4d, 0x7c, 0x70
    , 0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70, 0xc8, 0xf8, 0x57, 0x60
    , 0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60, 0xcb, 0x88, 0xf0, 0x70
    , 0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0, 0xd3, 0x75, 0xe4, 0xf0
    , 0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0, 0xd6, 0x20, 0xbf, 0xe0
    , 0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0, 0xd9, 0x15, 0x8a, 0xf0
    , 0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70, 0xdb, 0xc0, 0x65, 0xe0
    , 0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60, 0xde, 0xbe, 0x6b, 0x70
    , 0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70, 0xe1, 0x69, 0x46, 0x60
    , 0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60, 0xe4, 0x5e, 0x11, 0x70
    , 0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0, 0xe7, 0x37, 0x10, 0xe0
    , 0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0, 0xea, 0x06, 0xf1, 0xf0
    , 0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0, 0xec, 0xd6, 0xb6, 0xe0
    , 0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60, 0xef, 0xaf, 0xd2, 0x70
    , 0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70, 0xf2, 0x7f, 0x97, 0x60
    , 0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60, 0xf5, 0x4f, 0x78, 0x70
    , 0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70, 0xf8, 0x28, 0x77, 0xe0
    , 0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0, 0xfa, 0xf8, 0x58, 0xf0
    , 0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0, 0xfd, 0xc8, 0x1d, 0xe0
    , 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0, 0x00, 0x97, 0xfe, 0xf0
    , 0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0, 0x03, 0x70, 0xfe, 0x60
    , 0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60, 0x06, 0x40, 0xdf, 0x70
    , 0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70, 0x09, 0x10, 0xa4, 0x60
    , 0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60, 0x0b, 0xe0, 0x85, 0x70
    , 0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70, 0x0e, 0xb9, 0x84, 0xe0
    , 0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0, 0x11, 0x89, 0x65, 0xf0
    , 0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0, 0x14, 0x59, 0x2a, 0xe0
    , 0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0, 0x17, 0x29, 0x0b, 0xf0
    , 0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0, 0x1a, 0x02, 0x0b, 0x60
    , 0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60, 0x1c, 0xd1, 0xec, 0x70
    , 0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70, 0x1f, 0xa1, 0xb1, 0x60
    , 0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60, 0x22, 0x55, 0xe2, 0xf0
    , 0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0, 0x25, 0x4a, 0x91, 0xe0
    , 0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0, 0x27, 0xfe, 0xc3, 0x70
    , 0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70, 0x2a, 0xea, 0x37, 0xe0
    , 0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60, 0x2d, 0x9e, 0x69, 0x70
    , 0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70, 0x30, 0x93, 0x18, 0x60
    , 0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60, 0x33, 0x47, 0x49, 0xf0
    , 0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0, 0x36, 0x32, 0xbe, 0x60
    , 0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0, 0x38, 0xe6, 0xef, 0xf0
    , 0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0, 0x3b, 0xdb, 0x9e, 0xe0
    , 0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0, 0x3e, 0x8f, 0xd0, 0x70
    , 0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70, 0x41, 0x84, 0x7f, 0x60
    , 0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60, 0x44, 0x2f, 0x76, 0x70
    , 0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0, 0x47, 0x2d, 0x5f, 0xe0
    , 0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0, 0x49, 0xb3, 0x6c, 0xf0
    , 0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70, 0x4c, 0xd6, 0x40, 0x60
    , 0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60, 0x4f, 0x5c, 0x4d, 0x70
    , 0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70, 0x52, 0x75, 0xe6, 0x60
    , 0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60, 0x54, 0xfb, 0xf3, 0x70
    , 0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0, 0x58, 0x1e, 0xc6, 0xe0
    , 0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0, 0x5a, 0xa4, 0xd3, 0xf0
    , 0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0, 0x5d, 0xbe, 0x6c, 0xe0
    , 0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0, 0x60, 0x4d, 0xb4, 0x70
    , 0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70, 0x63, 0x67, 0x4d, 0x60
    , 0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60, 0x65, 0xed, 0x5a, 0x70
    , 0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70, 0x69, 0x06, 0xf3, 0x60
    , 0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60, 0x6b, 0x96, 0x3a, 0xf0
    , 0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0, 0x6e, 0xaf, 0xd3, 0xe0
    , 0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0, 0x71, 0x35, 0xe0, 0xf0
    , 0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0, 0x74, 0x4f, 0x79, 0xe0
    , 0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60, 0x76, 0xde, 0xc1, 0x70
    , 0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70, 0x79, 0xf8, 0x5a, 0x60
    , 0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60, 0x7c, 0x7e, 0x67, 0x70
    , 0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70, 0x7f, 0x98, 0x00, 0x60
    , 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01
    , 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01
    , 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01
    , 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01
    , 0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
    , 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0xc7, 0xc0, 0x01
    , 0x00, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x04, 0xff, 0xff, 0xc7, 0xc0, 0x01
    , 0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c, 0x45, 0x44, 0x54, 0x00, 0x45
    , 0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00
    , 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32
    , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00
    , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x05, 0x00
    , 0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90, 0xff
    , 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff, 0x9f
    , 0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa2
    , 0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa5
    , 0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa8
    , 0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xaa
    , 0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xad
    , 0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xb0
    , 0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb3
    , 0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60, 0xff
    , 0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb6
    , 0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb9
    , 0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60, 0xff
    , 0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbb
    , 0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xbe
    , 0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc1
    , 0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc4
    , 0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xc7
    , 0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff, 0xca
    , 0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60, 0xff
    , 0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2
    , 0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd4
    , 0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd7
    , 0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd9
    , 0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xdc
    , 0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60, 0xff
    , 0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdf
    , 0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe2
    , 0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60, 0xff
    , 0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe5
    , 0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe8
    , 0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xea
    , 0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xed
    , 0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60, 0xff
    , 0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf0
    , 0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf3
    , 0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60, 0xff
    , 0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf6
    , 0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70, 0xff
    , 0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf9
    , 0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0, 0xff
    , 0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xfb
    , 0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0, 0xff
    , 0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfe
    , 0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01
    , 0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04
    , 0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x07
    , 0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00, 0x09
    , 0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0c
    , 0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f
    , 0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x12
    , 0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x15
    , 0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x18
    , 0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1a
    , 0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1d
    , 0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20
    , 0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x23
    , 0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x26
    , 0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x29
    , 0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x2b
    , 0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2e
    , 0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x31
    , 0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x34
    , 0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x37
    , 0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x39
    , 0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3c
    , 0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3f
    , 0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, 0x42
    , 0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, 0x45
    , 0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x47
    , 0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x4a
    , 0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x4d
    , 0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x50
    , 0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x53
    , 0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00, 0x56
    , 0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x58
    , 0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5b
    , 0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5e
    , 0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00, 0x61
    , 0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, 0x64
    , 0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x67
    , 0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00, 0x69
    , 0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x6c
    , 0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6f
    , 0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0, 0x00
    , 0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x72
    , 0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0, 0x00
    , 0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x74
    , 0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00, 0x78
    , 0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7a
    , 0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60, 0x00
    , 0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7d
    , 0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70, 0x00
    , 0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02
    , 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02
    , 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02
    , 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02
    , 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01
    , 0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7
    , 0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7
    , 0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54
    , 0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54
    , 0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
    , 0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x2c
    , 0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31
    , 0x2e, 0x30, 0x0a
};

#ifdef BSLS_PLATFORM_OS_WINDOWS
static const char *GMT_FILE              = "defaultzictest\\GMT";
static const char *ETC_UTC_FILE          = "defaultzictest\\Etc\\UTC";
static const char *AMERICA_NEW_YORK_FILE = "defaultzictest\\America\\New_York";
#else
static const char *GMT_FILE              = "defaultzictest/GMT";
static const char *ETC_UTC_FILE          = "defaultzictest/Etc/UTC";
static const char *AMERICA_NEW_YORK_FILE = "defaultzictest/America/New_York";
#endif

void writeData(const char *fileName, const char *data, int numBytes)
{
    int rc = bdls::FilesystemUtil::createDirectories(fileName, false);

    if (rc != 0) {
        // If this test-driver is being run in parallel, its possible for two
        // instances to attempt to create the directory simultaneously, and
        // for one of them to fail.  But the directory should still exist.

        bslmt::ThreadUtil::microSleep(0,1);
        bsl::string path(fileName);
        bdls::PathUtil::popLeaf(&path);
        ASSERT(bdls::FilesystemUtil::exists(path));
    }
//..
// Then we create a file for Bangkok and write the binary time zone data to
// that file.
//..
    bsl::ofstream outputFile(fileName, bsl::ofstream::binary);
    ASSERT(outputFile.is_open());
    outputFile.write(reinterpret_cast<const char *>(data), numBytes);
    outputFile.close();
}

// ============================================================================
//                               MAIN PROGRAM
// ----------------------------------------------------------------------------

int main(int argc, char *argv[])
{
    int             test     = argc > 1 ? atoi(argv[1]) : 0;
    bool         verbose     = argc > 2;
    bool     veryVerbose     = argc > 3;
    bool veryVeryVerbose     = argc > 4;
    bool veryVeryVeryVerbose = argc > 5;

    bslma::TestAllocator        allocator;
    static bslma::TestAllocator defaultAllocator("dta", veryVeryVerbose);
    static bslma::TestAllocator globalAllocator("gta", veryVeryVerbose);;

    bslma::DefaultAllocatorGuard guard(&defaultAllocator);

    bslma::Default::setGlobalAllocator(&globalAllocator);

    if (veryVeryVerbose) {
        defaultAllocator.setVerbose(true);
    }

#ifdef BSLS_PLATFORM_OS_WINDOWS
    char zoneInfo[] = "BDE_ZONEINFO_ROOT_PATH=.\\defaultzictest";
#else
    char zoneInfo[] = "BDE_ZONEINFO_ROOT_PATH=./defaultzictest";
#endif

    putenv(zoneInfo);

    if (!bdls::FilesystemUtil::exists(AMERICA_NEW_YORK_FILE)) {
        writeData(AMERICA_NEW_YORK_FILE,
                  reinterpret_cast<const char  *>(AMERICA_NEW_YORK_DATA),
                  sizeof(AMERICA_NEW_YORK_DATA));
    }

    if (!bdls::FilesystemUtil::exists(ETC_UTC_FILE)) {
        writeData(ETC_UTC_FILE,
                  reinterpret_cast<const char  *>(ETC_UTC_DATA),
                  sizeof(ETC_UTC_DATA));
    }

    if (!bdls::FilesystemUtil::exists(GMT_FILE)) {
        writeData(GMT_FILE,
                  reinterpret_cast<const char  *>(GMT_DATA),
                  sizeof(GMT_DATA));
    }

    cout << "TEST " << __FILE__ << " CASE " << test << endl;

    switch (test) { case 0:
      case 6: {
        // --------------------------------------------------------------------
        // TESTING USAGE EXAMPLE
        //   The usage example provided in the component header file must
        //   compile, link, and run on all platforms as shown.
        //
        // Plan:
        //   Incorporate usage example from header into driver, remove leading
        //   comment characters, and replace 'assert' with 'ASSERT'.
        //
        // Testing:
        //   USAGE EXAMPLE
        // --------------------------------------------------------------------

        if (verbose) cout << endl << "TESTING USAGE EXAMPLE" << endl
                                  << "=====================" << endl;

//
// When the 'getLocalDescriptor' function is called without a specified
// Zoneinfo it obtains an answer from the binary files.  (Binary file
// initialization is not shown).
//..
    baltzo::LocalTimeDescriptor result;
    int rc = getLocalTimeDescriptor(&result,
                                    bdlt::Datetime(bdlt::Date(2011, 03, 21),
                                                  bdlt::Time(20, 57)),
                                    "America/New_York");
    ASSERT(0 == rc);
    ASSERT("EDT"  == result.description());
    ASSERT(true   == result.dstInEffectFlag());
    ASSERT(-14400 == result.utcOffsetInSeconds());
//..
///Example 2: Installing the Default Zoneinfo Cache Object
///- - - - - - - - - - - - - - - - - - - - - - - - - - - -
// In this example we demonstrate how to configure the default time-zone cache
// for a process.  Note that many application may not need to explicitly
// configure the default cache object, but can instead use the automatically
// configured default object.  Also note that the default time-zone cache is
// intended to be configured by the *owner* of 'main'.  The default object
// should be set during the initialization of an application (while the task
// has a single thread) and unset just prior to termination (when there is
// similarly a single thread):
//..
//  int main(int argc, const char *argv[])
//  {
//
//      // ...
//..
// First, we create and configure a 'baltzo::DataFileLoader' object:
//..
        baltzo::DataFileLoader loader;
        loader.configureRootPath(".");
//..
// Next, we use 'loader' to initialize a 'baltzo::ZoneinfoCache' object:
//..
        baltzo::ZoneinfoCache  cache(&loader);
//..
// Then, we create a 'baltzo::DefaultZoneinfoCacheScopedGuard' to set the
// default Zoneinfo cache for the lifetime of the guard, and then verify the
// value is correct.
//..
        {
            baltzo::DefaultZoneinfoCacheScopedGuard guard(&cache);
            ASSERT(&cache == baltzo::DefaultZoneinfoCache::defaultCache());

            // ...
//..
// At the end of this scope 'guard' is destroyed, and the default Zoneinfo
// cache is restored to its previous value.
//..
        }
        ASSERT(&cache != baltzo::DefaultZoneinfoCache::defaultCache());

        // ...

//  }
//..
      } break;
      case 5: {
        // --------------------------------------------------------------------
        // 'defaultCache' CLASS METHOD
        //
        // Concerns:
        //: 1 The installed global allocator does not allocate memory if
        //:   'cache' is specified and non-0.
        //:
        //: 2 The installed global allocator does not allocate memory if
        //:   'defaultCache' was previously called once with no argument.
        //:
        //: 3 The installed global allocator does not allocate memory if
        //:   'setDefaultCache' was previously called, passing a non-0
        //:   argument.
        //:
        //: 4 The installed global allocator does allocate memory if
        //:  'defaultCache' is called with no argument and 'defaultCache' was
        //:  not previously called,
        //:
        //: 5 Return the specified 'baltzo::ZoneinfoCache' address, if
        //:   specified, or the address of the default cache otherwise.
        //:
        //: 6 Return the address of a valid 'baltzo::ZoneinfoCache' if 0 is
        //:   passed in or no argument is specified, and 'setDefaultCache' was
        //:   not previously invoked with a non-0 argument.
        //:
        //: 7 Return the address of 'baltzo::ZoneinfoCache' set with a previous
        //:   call of 'setDefaultCache' if 0 is passed in or no argument is
        //:   specified.
        //:
        //: 8 Return the address of a valid 'baltzo::ZoneinfoCache' if 0 or no
        //:   argument are passed and 'setDefaultCache' was invoked with a 0
        //:   argument.
        //
        // Plan:
        //: 1 Invoking this method passing the address of a cache object, and
        //:   verifying that the same address is returned and no memory is
        //:   allocated by the global allocator.  (C-1, 5)
        //:
        //: 2 Invoke this method without passing the address of a cache object
        //:   and verify that a new default default-cache object is allocated
        //:   by the global allocator and its address is returned.  Also verify
        //:   that the same address is returned if 0 is passed.  (C-4, 2, 6)
        //:
        //: 3 Invoke this method with no arguments or specifying 0, after
        //:   setting a default cache with 'setDefaultCache', and verify that
        //:   the cache returned is the one set with 'setDefaultCache' and that
        //:   the global allocator does not allocate memory.  (C-3, 7)
        //:
        //: 4 Invoke this method with no arguments or specifying 0, after
        //:   setting to 0 the default cache with 'setDefaultCache', and verify
        //:   that the cache returned is the same default default-cache
        //:   returned at point 2 and that the global allocator does not
        //:   allocate memory.  (C-3, 7-8)
        //
        // Testing:
        //   defaultCache(baltzo::ZoneinfoCache *cache = 0)
        // --------------------------------------------------------------------

        if (verbose) cout << "\n'defaultCache' CLASS METHOD" << endl
                          << "=============================" << endl;

        baltzo::TestLoader loader;
        baltzo::ZoneinfoCache cache(&loader);

        baltzo::ZoneinfoCache *SYSTEM_DEFAULT = 0;

        if (verbose) cout << "\nPassing in a cache object and testing GA"
                          << endl;
        {
            const bsls::Types::Int64 GA_NUM_BYTES =
                                               globalAllocator.numBytesInUse();
            const baltzo::ZoneinfoCache *RESULT = Obj::defaultCache(&cache);
            LOOP2_ASSERT(L_, RESULT, &cache == RESULT);
            LOOP_ASSERT (L_, GA_NUM_BYTES == globalAllocator.numBytesInUse());

        }

        if (verbose) cout << "\nNot passing in a cache object and testing GA"
                          << endl;
        {
            // QOI: globalAllocator will allocate the strings when compiled in
            // the 32-bit mode, and will not allocate (short-string
            // optimization) in 64-bit mode.  The latter provides a larger
            // bufffer for the SSO.

            const bsls::Types::Int64 GA_NUM_BYTES =
                                               globalAllocator.numBytesInUse();
            SYSTEM_DEFAULT = Obj::defaultCache();
            LOOP2_ASSERT(L_, SYSTEM_DEFAULT, 0 != SYSTEM_DEFAULT);
            LOOP3_ASSERT(L_,
                         GA_NUM_BYTES,
                         globalAllocator.numBytesInUse(),
                         GA_NUM_BYTES <= globalAllocator.numBytesInUse());

            const bsls::Types::Int64 GA_NUM_BYTES2 =
                                               globalAllocator.numBytesInUse();
            const baltzo::ZoneinfoCache *RESULT = Obj::defaultCache(0);
            LOOP2_ASSERT(L_, RESULT, RESULT == SYSTEM_DEFAULT);
            LOOP_ASSERT (L_, GA_NUM_BYTES2 == globalAllocator.numBytesInUse());
        }

        if (verbose) cout << "\nTesting after 'setDefaultCache'"
                          << endl;
        {
            const bsls::Types::Int64 GA_NUM_BYTES =
                                               globalAllocator.numBytesInUse();
            Obj::setDefaultCache(&cache);
            LOOP_ASSERT (L_, GA_NUM_BYTES == globalAllocator.numBytesInUse());

            const bsls::Types::Int64 GA_NUM_BYTES2 =
                                               globalAllocator.numBytesInUse();
            const baltzo::ZoneinfoCache *RESULT = Obj::defaultCache();
            LOOP2_ASSERT(L_, RESULT, &cache == RESULT);
            LOOP_ASSERT (L_, GA_NUM_BYTES2 == globalAllocator.numBytesInUse());

            const bsls::Types::Int64 GA_NUM_BYTES3 =
                                               globalAllocator.numBytesInUse();
            RESULT = Obj::defaultCache(0);
            LOOP2_ASSERT(L_, RESULT, &cache == RESULT);
            LOOP_ASSERT (L_, GA_NUM_BYTES3 == globalAllocator.numBytesInUse());

            baltzo::ZoneinfoCache tempCache(&loader);
            const bsls::Types::Int64 GA_NUM_BYTES4 =
                                               globalAllocator.numBytesInUse();
            RESULT = Obj::defaultCache(&tempCache);
            LOOP2_ASSERT(L_, RESULT, &tempCache == RESULT);
            LOOP_ASSERT (L_, GA_NUM_BYTES4 == globalAllocator.numBytesInUse());
        }

        if (verbose) cout << "\nTesting after 'setDefaultCache(0)'"
                          << endl;
        {
            const bsls::Types::Int64 GA_NUM_BYTES =
                                               globalAllocator.numBytesInUse();
            Obj::setDefaultCache(0);
            LOOP_ASSERT (L_, GA_NUM_BYTES == globalAllocator.numBytesInUse());

            const bsls::Types::Int64 GA_NUM_BYTES2 =
                                               globalAllocator.numBytesInUse();
            const baltzo::ZoneinfoCache *RESULT = Obj::defaultCache();
            LOOP2_ASSERT(L_, RESULT, SYSTEM_DEFAULT == RESULT);
            LOOP_ASSERT (L_, GA_NUM_BYTES2 == globalAllocator.numBytesInUse());

            const bsls::Types::Int64 GA_NUM_BYTES3 =
                                               globalAllocator.numBytesInUse();
            RESULT = Obj::defaultCache(0);
            LOOP2_ASSERT(L_, RESULT, SYSTEM_DEFAULT == RESULT);
            LOOP_ASSERT (L_, GA_NUM_BYTES3 == globalAllocator.numBytesInUse());
        }

      } break;
      case 4: {
        // --------------------------------------------------------------------
        // 'setDefaultCache' CLASS METHOD
        //
        // Concerns:
        //: 1 The installed global allocator does not allocate memory.
        //:
        //: 2 Return the previously installed default 'baltzo::ZoneinfoCache'.
        //:
        //: 3 The cache passed in is set as the default one.
        //
        // Plan:
        // 1 Set the default cache to 'cache' and verify that the global
        //   allocator did not allocate memory.  (C-1, 2)
        //
        // 2 Set the default cache to 'cache2' and back to 'cache' and verify
        //   that the address of the previously set default cache is returned.
        //   (C-2, 3)
        //
        // 3 Negative testing.
        //
        // Testing:
        //   setDefaultCache(baltzo::ZoneinfoCache *cache)
        // --------------------------------------------------------------------

        if (verbose) cout << "\n'setDefaultCache' CLASS METHOD" << endl
                          << "==============================" << endl;

        baltzo::TestLoader loader;
        baltzo::ZoneinfoCache cache(&loader);
        baltzo::ZoneinfoCache cache2(&loader);

        if (verbose) cout << "\nTesting invoking 'setDefaultCache' and GA."
                          << endl;
        {
            const bsls::Types::Int64 GA_NUM_BYTES =
                                               globalAllocator.numBytesInUse();
            baltzo::ZoneinfoCache *cachePtr = Obj::setDefaultCache(&cache);
            LOOP2_ASSERT (L_, cachePtr, 0 == cachePtr);
            LOOP_ASSERT (L_, GA_NUM_BYTES == globalAllocator.numBytesInUse());
        }

        if (verbose) cout << "\nInvoking 'setDefaultCache' a second time."
                          << endl;

        {
            baltzo::ZoneinfoCache *cachePtr = Obj::setDefaultCache(&cache2);
            LOOP_ASSERT (L_, &cache == cachePtr);
        }

        {
            baltzo::ZoneinfoCache *cachePtr = Obj::setDefaultCache(&cache);
            LOOP_ASSERT (L_, &cache2 == cachePtr);
        }

        if (verbose) cout << "\nNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            if (veryVerbose) cout <<
                 "\t'CLASS METHOD 'setDefaultCache' " << endl;
            {
                baltzo::ZoneinfoCache cache(&loader);

                ASSERT_PASS(Obj::setDefaultCache(&cache));
            }
        }
      } break;
      case 3: {
        // --------------------------------------------------------------------
        // CLASS METHOD 'defaultZoneinfoDataLocation'
        //
        // Concerns:
        //: 1 Return the path specified by the environment variable
        //:   'BDE_ZONEINFO_ROOT_PATH' if set even if no Zoneinfo data is
        //:   present.
        //:
        //: 2 Return one of the platform-dependent default paths for Zoneinfo
        //:   data if 'BDE_ZONEINFO_ROOT_PATH' is not set and said directories
        //:   exist even if no Zoneinfo data is present.
        //:
        //: 3 Return current path if 'BDE_ZONEINFO_ROOT_PATH' is not set and
        //:   no default directories exist for the current platform.
        //:
        //: 4 The returned path is always null terminated.
        //:
        //: 5 A null pointer is never returned.
        //:
        //: 4 All memory allocation caused by the execution of this method is
        //:   temporary.
        //
        // Plan:
        // 1 Invoke the method with 'BDE_ZONEINFO_ROOT_PATH' set to
        // "./defaultzictest" and verify that the returned value has the same
        // value.  Also verify that the memory allocated by the default
        // allocator did not increase.  (C-1, 4, 5)
        //
        // 2 Invoke the method with 'BDE_ZONEINFO_ROOT_PATH' set to a path that
        //   does not contain Zoneinfo data and verify that the value returned
        //   is still the same as 'BDE_ZONEINFO_ROOT_PATH'.  (C-1, 4)
        //
        // 3 Invoke the method with 'BDE_ZONEINFO_ROOT_PATH' unset and verify
        //   that the value returned is one of the default paths for the
        //   platform if they exist or the current working directory.  Also
        //   verify that the memory allocated by the default allocator did not
        //   increase.  (C-2..4)
        //
        // Testing:
        //   defaultZoneinfoDataLocation()
        // --------------------------------------------------------------------

        if (verbose) cout << endl
                          << "'defaultZoneinfoDataLocation' CLASS METHOD"
                          << endl
                          << "==============================================="
                          << endl;

#ifndef BSLS_PLATFORM_OS_WINDOWS
        if (verbose) cout << "Testing with 'BDE_ZONEINFO_ROOT_PATH' set"
                          << endl;
        {
            const bsls::Types::Int64 DA_NUM_BYTES =
                                              defaultAllocator.numBytesInUse();
            const char *RESULT = Obj::defaultZoneinfoDataLocation();
            LOOP2_ASSERT(L_, RESULT, 0 == strcmp(RESULT, "./defaultzictest"));
            LOOP2_ASSERT(L_, defaultAllocator.numBytesInUse(),
                         DA_NUM_BYTES == defaultAllocator.numBytesInUse());
        }

        if (verbose) cout << "Testing with 'BDE_ZONEINFO_ROOT_PATH' set to an "
                          << "existing path not containing Zoneinfo data "
                          << "(expected to log a complaint)"
                          << endl;
        {
            char zoneInfo[] = "BDE_ZONEINFO_ROOT_PATH=/usr/bin/";
            putenv(zoneInfo);
            const char *RESULT = Obj::defaultZoneinfoDataLocation();
            LOOP2_ASSERT(L_, RESULT, 0 == strcmp(RESULT, "/usr/bin/"));
        }

        if (verbose) cout << "Testing with 'BDE_ZONEINFO_ROOT_PATH' unset"
                          << endl;
        {
            int rc = unsetenv("BDE_ZONEINFO_ROOT_PATH");
            ASSERT(0 == rc);

            const bsls::Types::Int64 DA_NUM_BYTES =
                                              defaultAllocator.numBytesInUse();

            const char *RESULT = Obj::defaultZoneinfoDataLocation();

            // TBD: find a better way to determine which path will be returned
            // on a build machine.

            // /bb/data/datetime/zoneinfo is Bloomberg-specific
            LOOP2_ASSERT( L_, RESULT,
                        0 == strcmp(RESULT, "/opt/bb/share/zoneinfo/")
                     || 0 == strcmp(RESULT, "/bb/data/datetime/zoneinfo/")
                     || 0 == strcmp(RESULT, "/usr/share/zoneinfo/")
                     || 0 == strcmp(RESULT, "/usr/share/lib/zoneinfo/")
                     || 0 == strcmp(RESULT, "."));

            LOOP2_ASSERT(L_, defaultAllocator.numBytesInUse(),
                         DA_NUM_BYTES == defaultAllocator.numBytesInUse());
        }
#else
        if (verbose) cout << "Testing with 'BDE_ZONEINFO_ROOT_PATH' set"
                          << endl;
        {
            const bsls::Types::Int64 DA_NUM_BYTES =
                                              defaultAllocator.numBytesInUse();

            const char *RESULT = Obj::defaultZoneinfoDataLocation();

            LOOP2_ASSERT(L_, RESULT,
                         0 == bsl::strcmp(RESULT, ".\\defaultzictest"));
            LOOP2_ASSERT(L_, defaultAllocator.numBytesInUse(),
                         DA_NUM_BYTES == defaultAllocator.numBytesInUse());
        }

        if (verbose) cout << "Testing with 'BDE_ZONEINFO_ROOT_PATH' set to an "
                          << "existing path not containing Zoneinfo data"
                          << endl;
        {
            _putenv((char *) "BDE_ZONEINFO_ROOT_PATH=\\C:\\Windows");

            const bsls::Types::Int64 DA_NUM_BYTES =
                                              defaultAllocator.numBytesInUse();

            const char *RESULT = Obj::defaultZoneinfoDataLocation();

            LOOP2_ASSERT(L_, RESULT,
                         0 == bsl::strcmp(RESULT, "\\C:\\Windows"));
            LOOP2_ASSERT(L_, defaultAllocator.numBytesInUse(),
                         DA_NUM_BYTES == defaultAllocator.numBytesInUse());
        }

        if (verbose) cout << "Testing with 'BDE_ZONEINFO_ROOT_PATH' unset"
                          << endl;
         {
            // TBD
            _putenv((char *) "BDE_ZONEINFO_ROOT_PATH=");

            const bsls::Types::Int64 DA_NUM_BYTES =
                                              defaultAllocator.numBytesInUse();

            const char *RESULT = Obj::defaultZoneinfoDataLocation();

            LOOP2_ASSERT(L_, RESULT, 0 == bsl::strcmp(RESULT, "."));
            LOOP2_ASSERT(L_, defaultAllocator.numBytesInUse(),
                         DA_NUM_BYTES == defaultAllocator.numBytesInUse());
        }
#endif
      } break;
      case 2: {
        // --------------------------------------------------------------------
        // CLASS METHOD 'loadDefaultZoneinfoDataLocations'
        //
        // Concerns:
        //: 1 The correct sequence of data locations is loaded.
        //:
        //: 2 0 is never loaded in the vector.
        //:
        //: 3 On the windows platform the empty vector is loaded.
        //:
        //: 4 Memory is allocated only by the parameter allocator.
        //
        // Plan:
        //:1 Create a table of expected values and test the output of the
        //:  operation (C-1,2).
        //:
        //:2 Install a test allocator in the output vector, and test the
        //:  default allocator does not change the number of bytes in use
        //:  before and after testing the operation (C-4)
        //:
        //:4 Test the vector is empty after the operation on windows (C-3)
        //:
        //
        // Testing:
        //   loadDefaultZoneinfoDataLocation()
        // --------------------------------------------------------------------
        if (verbose) cout << endl
                          << "'loadDefaultZoneinfoDataLocations' CLASS METHOD"
                          << endl
                          << "==============================================="
                          << endl;

        if (verbose) cout <<
                         "\nCreate a table of expected output values." << endl;

        struct TestData {
            int             d_line;
            const char     *d_path;
        } VALUES[] = {
            // LINE  EXP_PATH
            // ----  --------
            {L_,  "/opt/bb/share/zoneinfo/"},         // Bloomberg stnd loc.
            {L_,      "/bb/data/datetime/zoneinfo/"}, // deprctd. BB stnd loc.
            {L_,      "/usr/share/zoneinfo/"},        // Unix standard loc.
            {L_,      "/usr/share/lib/zoneinfo/"},    // Solaris standard loc.
        };
        const int NUM_VALUES = sizeof(VALUES) / sizeof(*VALUES);

        {
           if (verbose) cout <<
                           "\nCreate a test allocator and install "
                           "it in the return object" << endl;

           bslma::TestAllocator LA("object", veryVeryVeryVerbose);
           bsl::vector<const char *> locations(&LA);

           if (verbose) cout <<
                           "\nTest that all allocations are temporary" << endl;

            const bsls::Types::Int64 DA_NUM_BYTES =
                                              defaultAllocator.numBytesInUse();

            Obj::loadDefaultZoneinfoDataLocations(&locations);
            LOOP2_ASSERT(L_, defaultAllocator.numBytesInUse(),
                         DA_NUM_BYTES == defaultAllocator.numBytesInUse());

#ifndef BSLS_PLATFORM_OS_WINDOWS
            // Make sure 'locations' contains the same number of paths as
            // expected.

            LOOP2_ASSERT(L_, locations.size(),
                         NUM_VALUES == locations.size());

            // Verify that the paths correspond to the expected values.

            for (int i = 0; i < NUM_VALUES; ++i) {
                const int   LINE        = VALUES[i].d_line;
                const char *EXP_PATH    = VALUES[i].d_path;
                const char *RESULT_PATH = locations[i];

                if (veryVerbose) {
                     T_ P_(LINE) P_(EXP_PATH) P(RESULT_PATH)
                }

                LOOP2_ASSERT(LINE, EXP_PATH,
                             0 == bsl::strcmp(RESULT_PATH, EXP_PATH));
            }
#else
            // As of now Windows does not have any default paths.

            LOOP2_ASSERT(L_, locations.size(), 0 == locations.size());
#endif
        }

        if (verbose) cout << "\nNegative Testing." << endl;
        {
            bsls::AssertTestHandlerGuard hG;

            if (veryVerbose) cout <<
                 "\t'CLASS METHOD 'loadDefaultZoneinfoDataLocations' " << endl;
            {
                bsl::vector<const char *> parameter;

                ASSERT_PASS(Obj::loadDefaultZoneinfoDataLocations(&parameter));
                ASSERT_FAIL(Obj::loadDefaultZoneinfoDataLocations(0));
            }
        }
      } break;
      case 1: {
        // --------------------------------------------------------------------
        // BREATHING TEST:
        //   Developers' Sandbox.
        //
        // Plan:
        //   Perform and ad-hoc test of the primary modifiers and accessors.
        //
        // Testing:
        //   This "test" *exercises* basic functionality, but *tests* nothing.
        // --------------------------------------------------------------------

        if (verbose) cout << endl << "BREATHING TEST" << endl
                                  << "==============" << endl;

        baltzo::ZoneinfoCache *DUMMY1 = (baltzo::ZoneinfoCache *) 0x01;
        baltzo::ZoneinfoCache *DUMMY2 = (baltzo::ZoneinfoCache *) 0x02;

        if (verbose) cout << endl << "Testing the system default cache"
                          << endl;

        const baltzo::ZoneinfoCache *SYSTEMDEFAULTCACHE = Obj::defaultCache();
        ASSERT(0 != SYSTEMDEFAULTCACHE);
        ASSERT(SYSTEMDEFAULTCACHE == Obj::defaultCache());

        if(veryVerbose) cout << "Loading Etc/UTC" << endl;
        {
            const char *ID = "Etc/UTC";
            ASSERT(0 == Obj::defaultCache()->lookupZoneinfo(ID));

            const baltzo::Zoneinfo *TZ = Obj::defaultCache()->getZoneinfo(ID);
            ASSERT(0 != TZ) ;
            ASSERT(1 == TZ->numTransitions());
        }

        {
            if(veryVerbose) cout << "\nLoading America/New_York" << endl;
            const char *ID = "America/New_York";
            ASSERT(0 == Obj::defaultCache()->lookupZoneinfo(ID));

            const baltzo::Zoneinfo *TZ = Obj::defaultCache()->getZoneinfo(ID);
            ASSERT(0   != TZ);
            ASSERT(237 == TZ->numTransitions());
        }

        if (verbose) cout << "\nTesting user defind default caches"
                          << endl;

        ASSERT(0 != Obj::defaultCache(0));
        ASSERT(DUMMY1 == Obj::defaultCache(DUMMY1));
        ASSERT(DUMMY2 == Obj::defaultCache(DUMMY2));

        ASSERT(0 == Obj::setDefaultCache(DUMMY1));
        ASSERT(DUMMY1 == Obj::defaultCache());
        ASSERT(DUMMY1 == Obj::defaultCache(0));
        ASSERT(DUMMY1 == Obj::defaultCache(DUMMY1));
        ASSERT(DUMMY2 == Obj::defaultCache(DUMMY2));

        ASSERT(DUMMY1 == Obj::setDefaultCache(DUMMY2));
        ASSERT(DUMMY2 == Obj::defaultCache());
        ASSERT(DUMMY2 == Obj::defaultCache(0));
        ASSERT(DUMMY1 == Obj::defaultCache(DUMMY1));
        ASSERT(DUMMY2 == Obj::defaultCache(DUMMY2));

        ASSERT(DUMMY2 == Obj::setDefaultCache(0));
        ASSERT(DUMMY1 == Obj::defaultCache(DUMMY1));
        ASSERT(DUMMY2 == Obj::defaultCache(DUMMY2));
        ASSERT(SYSTEMDEFAULTCACHE == Obj::defaultCache());

      } break;
      default: {
        cerr << "WARNING: CASE `" << test << "' NOT FOUND." << endl;
        testStatus = -1;
      }
    }

    if (testStatus > 0) {
        cerr << "Error, non-zero test status = " << testStatus << "." << endl;
    }

    // TBD: multiple test cases use the same path and so cleanup can not occur
    //      after each test case ends, or else there is a race condition when
    //      multiple test cases are run in parallel
    //bdls::FilesystemUtil::remove("defaultzictest", true);

    return testStatus;
}

// ----------------------------------------------------------------------------
// Copyright 2015 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
